package cn.woochen.mvvmframe.config

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.*
import cn.woochen.comlib.BaseViewModel
import cn.woochen.comlib.config.IBaseView
import kotlinx.coroutines.launch
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class BaseViewGroup<VM : BaseViewModel> : IBaseView, ViewModelStoreOwner, LifecycleObserver {

    protected var mContext: Context? = null
    lateinit var mViewModel: VM
    protected var mOwner: LifecycleOwner? = null

    //定义ViewModelStore变量
    private var mViewModelStore: ViewModelStore = ViewModelStore()

    constructor(fragment: Fragment) : super() {
        fragment.lifecycle.addObserver(this)
        if (fragment.activity != null) {
            mContext = fragment.activity
        }
        initViewModel()
        registerNecessaryObserver(fragment)
    }

    constructor(activity: AppCompatActivity) : super() {
        activity.lifecycle.addObserver(this)
        mContext = activity
        initViewModel()
        registerNecessaryObserver(activity)
    }

    private fun initViewModel() {
        mViewModel = createViewModel()
    }

    /**
     * 注册必要的观察者
     */
    protected open fun registerNecessaryObserver(owner: LifecycleOwner) {
        mOwner = owner
        owner.lifecycleScope.launch {
            mViewModel.loadingChange.showDialog.collect {
                showLoading(it)
            }
        }
        owner.lifecycleScope.launch {
            mViewModel.loadingChange.dismissDialog.collect {
                showContent()
            }
        }
    }

    protected fun createViewModel(): VM {
        return ViewModelProvider(this)
            .get(getVmClazz(this))
    }

    /**
     * 获取任意对象的泛型信息，返回一个继承了BaseViewModel的字节码对象
     */
    private fun getVmClazz(obj: Any): Class<VM> {
        var cls: Class<*>? = obj.javaClass
        var vmClass: Class<VM>? = null
        while (vmClass == null && cls != null) {
            vmClass = getVMClass(cls)
            cls = cls.superclass
        }
        if (vmClass == null) {
            vmClass = BaseViewModel::class.java as Class<VM>
        }
        return vmClass
    }

    private fun getVMClass(cls: Class<*>): Class<VM>? {
        val type: Type? = cls.genericSuperclass
        if (type is ParameterizedType) {
            val types: Array<Type> = type.actualTypeArguments
            for (t in types) {
                if (t is Class<*>) {
                    if (BaseViewModel::class.java.isAssignableFrom(t)) {
                        return t as Class<VM>
                    }
                } else if (t is ParameterizedType) {
                    val rawType: Type = t.rawType
                    if (rawType is Class<*>) {
                        if (BaseViewModel::class.java.isAssignableFrom(rawType)) {
                            return rawType as Class<VM>
                        }
                    }
                }
            }
        }
        return null
    }

    override fun showLoading(content: String) {
        if (mContext is BaseActivity<*, *>) {
            (mContext as BaseActivity<*, *>).showLoading(content)
        }
    }

    override fun showContent() {
        if (mContext is BaseActivity<*, *>) {
            (mContext as BaseActivity<*, *>).showContent()
        }
    }

    override fun showError() {
        if (mContext is BaseActivity<*, *>) {
            (mContext as BaseActivity<*, *>).showError()
        }
    }

    override fun showEmpty() {
        if (mContext is BaseActivity<*, *>) {
            (mContext as BaseActivity<*, *>).showEmpty()
        }
    }

    override fun getViewModelStore(): ViewModelStore = mViewModelStore

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private fun release() {
        mContext = null
        releaseResource()
    }

    protected open fun releaseResource() {

    }


}